import type { TableProps, TableRefs } from "element-plus";
import type { PropType, Slots } from "vue";
import type { TableSize } from "./types";
import { defineComponent, onMounted, provide, ref } from "vue";
import Pagination from "./components/Pagination";
import TableToolbars from "./components/toolbars";
import { SYMBOL_FETCH_DATA, SYMBOL_INIT_SLOTS, SYMBOL_SET_FILTERED_SLOTS, SYMBOL_SET_TABLE_SIZE, SYMBOL_TABLE_SIZE } from "./types";

interface Props extends Partial<TableProps<Record<keyof any, any>>> {
    /** 表格加载状态 */
    loading: boolean;
    /** 分页参数, 传入 false 表示不使用分页 */
    page: Page | false;
    /** 用于重新加载以及分页获取数据, 方法不应该具有形参, 应当使用回调方式传递 */
    fetchData: () => void;
    /** 是否在挂载后立即获取数据 */
    fetchImmediately?: boolean;
}

/** 封装 el-table, 统一系统表格, 同时添加更多功能 */
export default defineComponent((props: Props, { attrs, slots, expose }) => {
    /** el-table 组件实例 */
    const tableRef = ref<TableRefs>();

    provide(SYMBOL_FETCH_DATA, props.fetchData);

    /** 表格尺寸 */
    const tableSize = ref<TableSize>(props.size as TableSize);
    provide(SYMBOL_TABLE_SIZE, tableSize);
    provide(SYMBOL_SET_TABLE_SIZE, (size: TableSize) => {
        tableSize.value = size;
    });

    /** 获取过滤后的插槽 */
    const filteredSlots = ref(slots);
    provide(SYMBOL_INIT_SLOTS, slots);
    provide(SYMBOL_SET_FILTERED_SLOTS, (s: Slots) => {
        filteredSlots.value = s;
    });

    onMounted(() => {
        if (props.fetchImmediately) props.fetchData();
    });

    // 通过 ref 暴露 el-table 实例, 以便父组件能直接操作 el-table
    expose({
        innerTableRef: tableRef,
    });

    return () => (
        <div v-loading={props.loading}>
            <el-table ref={tableRef} border={props.border} size={tableSize.value} {...attrs} v-slots={filteredSlots.value} />
            <div class="flex-between-c mt-4">
                <TableToolbars />
                {props.page !== false && <Pagination page={props.page} />}
            </div>
        </div>
    );
}, {
    name: "ElPageTable",
    props: {
        loading: {
            type: Boolean,
            required: true,
        },
        size: {
            type: String as PropType<TableSize>,
            default: "default",
        },
        border: {
            type: Boolean,
            default: true,
        },
        page: {
            type: [Object, Boolean] as PropType<Page | false>,
            required: true,
        },
        fetchData: {
            type: Function as PropType<() => void>,
            required: true,
        },
        fetchImmediately: {
            type: Boolean,
            default: true,
        },
    },
});
